﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.XLANGs.BaseTypes;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.Samples.BizTalk.Adapter.Common;
using System.Xml;

namespace com.fluister.BizTalk0MQAdapter.BizTalk0MQSendAdapter
{
    /// <summary>
    /// This class maintains send port properties associated with a message. These properties
    /// will be extracted from the message context for static send ports.
    /// </summary>
    public class BizTalk0MQAdapterProperties : ConfigProperties
    {
        private static string[] Methods = new string[] { "PUB", "REQ_REP"};
        private static string protocolAlias = "0MQ://";

        public enum AuthenticationType
        {
            AnonymousAuthentication,
            KerberosAuthentication
        }

        // Handler properties...
        private static int handlerTimeout = 120000;

        // Endpoint properties...
        private string method;
        private int timeout = BizTalk0MQAdapterProperties.handlerTimeout;
        private string contentType = "text/xml";
        private AuthenticationType authType = 0;
        private string uri;
        public string Uri { get { return uri; } }

        private static PropertyBase isSolicitResponseProp = new BTS.IsSolicitResponse();

        // If we needed to use SSO we will need this extra property. It is set in the
        // LocationConfiguration method below.
        // Additionally:
        //   TransmitLocation.xsd in the design-time project must also be edited to
        //   expose the necessary SSO properties.
        //   DotNetFileAsyncTransmitterBatch.cs within the run-time project must be
        //   edited to retrieve and populate the SSOResult class.
        //private string ssoAffiliateApplication;
        //public string AffiliateApplication { get { return ssoAffiliateApplication; } }

        private bool _isTwoWay;

        public bool IsTwoWay { get { return _isTwoWay; } }

        public BizTalk0MQAdapterProperties(IBaseMessage message, string propertyNamespace)
        {
            XmlDocument locationConfigDom = null;

            //  get the adapter configuration off the message
            string config = (string)message.Context.Read("AdapterConfig", propertyNamespace);
            this._isTwoWay = (bool)message.Context.Read(isSolicitResponseProp.Name.Name, isSolicitResponseProp.Name.Namespace);

            //  the config can be null all that means is that we are doing a dynamic send
            if (null != config)
            {
                locationConfigDom = new XmlDocument();
                locationConfigDom.LoadXml(config);

                //  For Dynamic Sends the Location config can be null
                //  Location properties - possibly override some handler properties
                this.LocationConfiguration(locationConfigDom);
            }
        }

        public BizTalk0MQAdapterProperties(string uri)
        {
            this.uri = uri;
            UpdateUriForDynamicSend();
        }

        public string Method
        {
            get { return this.method; }
        }

        public int Timeout
        {
            get { return this.timeout; }
        }

        public string ContentType
        {
            get { return this.contentType; }
        }

        public AuthenticationType AuthType
        {
            get { return this.authType; }
        }

        public static void TransmitHandlerConfiguration(XmlDocument configDOM)
        {
            // Handler properties
            BizTalk0MQAdapterProperties.handlerTimeout = ExtractInt(configDOM, "/Config/timeout");
        }

        public void LocationConfiguration(XmlDocument configDOM)
        {
            // Uri must exist (all static send port scenarios!)
            this.uri = Extract(configDOM, "Config/uri", null);

            this.method = ExtractMethod(configDOM);
            this.timeout = IfExistsExtractInt(configDOM, "/Config/timeout", 0);
            this.contentType = Extract(configDOM, "/Config/contentType", string.Empty);        
        }


        private string ExtractMethod(XmlDocument configDOM)
        {
            string method;

            string hv = IfExistsExtract(configDOM, "/Config/method", "1");

            switch (hv)
            {
                case "0":
                    method = Methods[0];
                    break;
                case "1":
                    method = Methods[1];
                    break;
                default:
                    method = Methods[0];
                    break;
            }

            return method;
        }

        public void UpdateUriForDynamicSend()
        {
            // Strip off the adapters alias
            if (this.uri.StartsWith(protocolAlias, StringComparison.OrdinalIgnoreCase))
            {
                string newUri = this.uri.Substring(protocolAlias.Length);
                this.uri = newUri;
            }
        }
    }
}
